package com.cy.pj.sys.service.realm;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;

import com.cy.pj.sys.Dao.SysMenuDao;
import com.cy.pj.sys.Dao.SysRoleMenuDao;
import com.cy.pj.sys.Dao.SysUserDao;
import com.cy.pj.sys.Dao.SysUserRoleDao;
import com.cy.pj.sys.pojo.SysUser;

@Service
public class ShiroUserRealm extends AuthorizingRealm{
	@Autowired
	private SysUserDao sysUserDao;
	@Autowired
	private SysUserRoleDao sysUserRoleDao;
	@Autowired
	private SysRoleMenuDao sysRoleMenuDao;
	@Autowired
	private SysMenuDao sysMenuDao;
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//1.获取登录用户信息，例如用户id
				SysUser user=(SysUser)principals.getPrimaryPrincipal();
				Integer userId=user.getId();
				//2.基于用户id获取用户拥有的角色(sys_user_roles)
				List<Integer> roleIds=
				sysUserRoleDao.findRoleIdsByUserId(userId);
				if(roleIds==null||roleIds.size()==0)
				throw new AuthorizationException();
				//3.基于角色id获取菜单id(sys_role_menus)
				List<Integer> menuIds=
				sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
			    if(menuIds==null||menuIds.size()==0)
			    throw new AuthorizationException();
				//4.基于菜单id获取权限标识(sys_menus)
			    List<String> permissions=
			    sysMenuDao.findPermissions(menuIds);
				//5.对权限标识信息进行封装并返回
			    Set<String> set=new HashSet<>();
			    for(String per:permissions){
			    	if(!StringUtils.isEmpty(per)){
			    		set.add(per);
			    	}
			    }
			    SimpleAuthorizationInfo info=
			    new SimpleAuthorizationInfo();
			    info.setStringPermissions(set);
				return info;//返回给授权管理器
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//1.获取用户名 用户页面输入的
		UsernamePasswordToken upToken=(UsernamePasswordToken)token;
		String username=upToken.getUsername();
		SysUser user=sysUserDao.findUserByUserName(username);
		//3.判断查询的用户是否存在
		if(user==null) {
			throw new UnknownAccountException();//Shiro框架未知的用户名异常
		}
		//4.判断用户是否被禁用
		if(user.getValid()==0) {
			throw new LockedAccountException(); //账号锁定异常
		}
		//5.封装用户信息
		//定义盐值
		ByteSource credentialsSalt=ByteSource.Util.bytes(user.getSalt());
		SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(
				user, //用户身份
				user.getPassword(), 
				credentialsSalt, //盐值
				getName());
		//返回封装结果
		return info;
	}
	//设置加密算法
	@Override
	public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
		//构建加密对象
		HashedCredentialsMatcher cMatcher=new HashedCredentialsMatcher();
		//设置加密算法
		cMatcher.setHashAlgorithmName("MD5");
		//设置加密次数
		cMatcher.setHashIterations(1);
		super.setCredentialsMatcher(cMatcher);
	}
	
}
